<?php

namespace Fize\Third\WechatWork;

use Fize\Third\WechatWork\Qyapi\Ticket;

/**
 * JS-SDK
 *
 * 本接口非微信直接提供
 */
class JsSdk extends QyapiAbstract
{

    /**
     * JSAPI票据类型 - 企业
     */
    const JSAPI_TICKET_TYPE_CORP = 'corp';

    /**
     * JSAPI票据类型 - 应用
     */
    const JSAPI_TICKET_TYPE_AGENT = 'agent';

    /**
     * @var bool 是否初始化时马上检测AccessToken
     */
    protected $checkAccessToken = false;

    /**
     * 获取JsApi权限验证配置
     * @param string      $url               网页的URL，自动处理#及其后面部分，为空则签名当前页
     * @param int         $timestamp         当前时间戳 (为空则自动生成)
     * @param string      $noncestr          随机串 (为空则自动生成)
     * @param string|null $jsapi_ticket_type JSAPI票据类型
     * @return array
     */
    public function getConfigSignature(string $url = '', int $timestamp = 0, string $noncestr = '', string $jsapi_ticket_type = null): array
    {
        if (!$timestamp) {
            $timestamp = time();
        }
        if (!$noncestr) {
            $noncestr = uniqid();
        }
        $ret = strpos($url, '#');
        if ($ret) {
            $url = substr($url, 0, $ret);
        }
        $url = trim($url);
        if (empty($url)) {
            $protocol = 'http://';
            if ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443)) {
                $protocol = 'https://';
            }
            $host = $_SERVER['HTTP_HOST'] ?? '';
            $uri = $_SERVER['REQUEST_URI'] ?? '';
            $url = $protocol . $host . $uri;
        }

        if (is_null($jsapi_ticket_type)) {
            $jsapi_ticket_type = self::JSAPI_TICKET_TYPE_CORP;
        }
        if ($jsapi_ticket_type == self::JSAPI_TICKET_TYPE_AGENT) {
            $jsapi_ticket = $this->getAgentJsApiTicket();
        } else {
            $jsapi_ticket = $this->getJsApiTicket();
        }

        $arrdata = [
            "jsapi_ticket" => $jsapi_ticket,
            "timestamp"    => $timestamp,
            "noncestr"     => $noncestr,
            "url"          => $url
        ];
        $signnature = $this->getSignature($arrdata);
        return [
            "jsapi_ticket" => $jsapi_ticket,
            "noncestr"     => $noncestr,
            "timestamp"    => $timestamp,
            "url"          => $url,
            "signature"    => $signnature
        ];
    }

    /**
     * 获取应用JsApi权限验证配置
     * @param string $url       网页的URL，自动处理#及其后面部分，为空则签名当前页
     * @param int    $timestamp 当前时间戳 (为空则自动生成)
     * @param string $noncestr  随机串 (为空则自动生成)
     * @return array
     */
    public function getAgentConfigSignature(string $url = '', int $timestamp = 0, string $noncestr = ''): array
    {
        return $this->getConfigSignature($url, $timestamp, $noncestr, self::JSAPI_TICKET_TYPE_AGENT);
    }

    /**
     * 获取企业jsapi_ticket
     * @return string
     */
    private function getJsApiTicket(): string
    {
        $cacheKey = $this->cacheKeyPre . '_JSAPI_TICKET_' . $this->corpid;
        $jsapiTicketCache = $this->cache->get($cacheKey);
        if ($jsapiTicketCache) {
            return $jsapiTicketCache;
        }

        $qyapi = new Qyapi($this->corpid, $this->corpsecret, $this->debug, $this->options);
        $result = $qyapi->getJsapiTicket();
        $expire = $result['expires_in'] ? intval($result['expires_in']) - 100 : 7200;
        $this->cache->set($cacheKey, $result['ticket'], $expire);
        return $result['ticket'];
    }

    /**
     * 获取应用jsapi_ticket
     * @return string
     */
    private function getAgentJsApiTicket(): string
    {
        $cacheKey = $this->cacheKeyPre . '_AGENT_JSAPI_TICKET_' . $this->corpid;
        $jsapiTicketCache = $this->cache->get($cacheKey);
        if ($jsapiTicketCache) {
            return $jsapiTicketCache;
        }

        $ticket = new Ticket($this->corpid, $this->corpsecret, $this->debug, $this->options);
        $result = $ticket->get();
        $expire = $result['expires_in'] ? intval($result['expires_in']) - 100 : 7200;
        $this->cache->set($cacheKey, $result['ticket'], $expire);
        return $result['ticket'];
    }

    /**
     * 获取签名
     * @param array $arrdata 签名数组
     * @return string 签名值
     */
    private function getSignature(array $arrdata): string
    {
        ksort($arrdata);
        $paramstring = "";
        foreach ($arrdata as $key => $value) {
            if (strlen($paramstring) == 0) {
                $paramstring .= $key . "=" . $value;
            } else {
                $paramstring .= "&" . $key . "=" . $value;
            }
        }
        return sha1($paramstring);
    }
}
